home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickTime / Programming Stuff / Documentation / develop articles / develop Issue 14 / Derived Media Handlers code / MyMediaComponent / MyMediaComponentRoutines.c < prev    next >
Encoding:
Text File  |  1993-02-25  |  12.6 KB  |  386 lines  |  [TEXT/KAHL]

  1. //--------------------------------------------------------------------------
  2. //
  3. //        MyMediaComponentRoutines.c
  4. //            by John Wang
  5. //
  6. //        Version:    1.0        02/25/93    Based on MyComponent shell.
  7. //
  8. //--------------------------------------------------------------------------
  9.  
  10. //
  11. //    #includes
  12. //
  13.  
  14. #include    <Components.h>
  15. #include    <Movies.h>
  16. #include    <MediaHandlers.h>
  17. #include    "MyMediaComponent.h"
  18. #include    "MyMediaComponentRoutines.h"
  19. #include    "MyMemory.h"
  20. #include    "QDrawHandler.h"
  21.  
  22. //--------------------------------------------------------------------------
  23.  
  24. pascal ComponentResult MyMediaInitialize(PrivateGlobals **storage,
  25.                                         GetMovieCompleteParams    *gmc)
  26. {
  27.     if (DEBUGME)
  28.         DebugStr("\PIn MyMediaInitialize()");
  29.  
  30.     //    Set characteristics
  31.     (**storage).myMovie = gmc->theMovie;
  32.     (**storage).myTrack = gmc->theTrack;
  33.     (**storage).myMedia = gmc->theMedia;
  34.     (**storage).mediaRate = gmc->effectiveRate;
  35.     SetRect(&((**storage).graphicsBox), 0, 0,
  36.                 (short) (gmc->width >> 16), (short) (gmc->height >> 16));
  37.     (**storage).trackMatrix = gmc->trackMovieMatrix;
  38.     (**storage).port = gmc->moviePort;
  39.     (**storage).device = gmc->movieGD;
  40.     (**storage).sampleDescIndex = -1;
  41.  
  42.     //    Set MediaIdle globals
  43.     (**storage).somethingChanged = 0xffff;
  44.     (**storage).enabled = FALSE;
  45.     (**storage).newMediaRate = gmc->effectiveRate;
  46.     (**storage).lastMediaTime = -1;
  47.     
  48.     //    Return and tell the base media handler our capabilities:
  49.     //        1)    handlerHasSpatial: tell handler that we draw.
  50.     //        2)    HandlerCanTransferMode: we want to be able to overlap onto another track.
  51.     //        3)    handlerNeedsBuffer: we want to use an offscreen buffer so that we don't
  52.     //                do compositing on the screen.  Remove flag to see the affects of compositing
  53.     //                on screen.
  54.     return(MediaSetHandlerCapabilities((**storage).self,
  55.                 handlerHasSpatial | handlerCanTransferMode | handlerNeedsBuffer, -1));
  56. }
  57.  
  58. //--------------------------------------------------------------------------
  59.  
  60. pascal ComponentResult MyMediaIdle(PrivateGlobals **storage,
  61.                                         TimeValue atMediaTime, long flagsIn,
  62.                                         long *flagsOut, const TimeRecord *movieTime)
  63. {
  64.     //    Media characteristics - preinitialized
  65.     Movie                        theMovie = (**storage).myMovie;
  66.     Track                        theTrack = (**storage).myTrack;
  67.     Media                        theMedia = (**storage).myMedia;
  68.     Fixed                        theRate = (**storage).mediaRate;
  69.     Rect                        theGraphicsBox = (**storage).graphicsBox;
  70.     MatrixRecord                theTrackMatrix = (**storage).trackMatrix;
  71.     CGrafPtr                    thePort = (**storage).port;
  72.     GDHandle                    theGDH = (**storage).device;
  73.     long                        theSampleIndex = (**storage).sampleDescIndex;
  74.     
  75.     //    Media globals - preinitialized
  76.     long                        theChanged = (**storage).somethingChanged;
  77.     Boolean                        theEnabled = (**storage).enabled;
  78.     Fixed                        theNewRate = (**storage).newMediaRate;
  79.     TimeValue                    theLastMediaTime = (**storage).lastMediaTime;
  80.     
  81.     //    MCIdle variables
  82.     OSErr                        err;
  83.     GDHandle                    saveGD;
  84.     CGrafPtr                    savePort;
  85.     Rect                        myDrawRect;
  86.     Boolean                        myRedraw;
  87.     Boolean                        done;
  88.     TimeValue                    theTime;
  89.     
  90.     //    Working sample
  91.     PicHandle                    myPic;
  92.     long                        mySize;
  93.     TimeValue                    mySampleTime;
  94.  
  95.     //    Current sample
  96.     PicHandle                    currPic;
  97.     TimeValue                    currSampleTime;
  98.     long                        currSampleIndex;
  99.  
  100.     if (DEBUGME)
  101.         DebugStr("\PIn MyMediaIdle()");
  102.  
  103.     //    Initialize by clearing err, saving GWorld, setting to movie GWorld, and creating handles.
  104.     err = noErr;
  105.     myPic = (PicHandle) MyNewHandle(sizeof(Picture));
  106.     currPic = (PicHandle) MyNewHandle(sizeof(Picture));
  107.     if (myPic == nil || currPic == nil) {
  108.         MyDisposeHandle((Handle *) &myPic);
  109.         MyDisposeHandle((Handle *) &currPic);
  110.         return(memFullErr);    //    Make sure this happens before changing GWorld
  111.     }
  112.     GetGWorld (&savePort, &saveGD);
  113.     SetGWorld ((GWorldPtr) thePort, theGDH);
  114.     
  115.     //    Get info about current sample: currPic, currSampleTime, and currSampleIndex
  116.     if ((err = GetMediaSample(theMedia, (Handle) currPic, 0, nil,
  117.             atMediaTime, &currSampleTime, nil, nil, &currSampleIndex, 0, nil, nil))) {
  118.         DebugStr("\PGetMediaSample failed.  Do not continue.");
  119.     }
  120.  
  121.     //    Check to see if sample desc index changed since the last sample.  If the current
  122.     //    sample contents have been changed, the our SampleDescChanged routine is called
  123.     if (currSampleIndex != theSampleIndex) {
  124.         theSampleIndex = (**storage).sampleDescIndex = currSampleIndex;
  125.         (**storage).somethingChanged |= kSampleDescChanged;
  126.     }
  127.  
  128.     //    If anything in the media changed, we can expect the theChanged boolean to be true.
  129.     //    In that case, we need to figure out what has changed and fix things.
  130.     myRedraw = FALSE;
  131.     if (theChanged) {
  132.         //    Go through each flag one by one.
  133.         if (theChanged & kSetActive) {
  134.             myRedraw = theEnabled | myRedraw;    //    If enabled, then start over, else don't change.
  135.         }
  136.         if (theChanged & kSetRate) {
  137.             if ((theRate < 0 && theNewRate > 0) ||
  138.                 (theRate > 0 && theNewRate < 0)) {
  139.                 myRedraw = TRUE;    //    If we start playing opposite dir., we start over.
  140.             }
  141.             theRate = (**storage).mediaRate = theNewRate;    //    Update it!!!
  142.         }
  143.         if (theChanged & kTrackEdited) {
  144.             myRedraw = TRUE;    //    If edited, then start over.
  145.         }
  146.         if (theChanged & kSetGWorld) {
  147.             myRedraw = TRUE;    //    If new GWorld, then start over.
  148.         }
  149.         if (theChanged & kSetDimensions) {
  150.             myRedraw = TRUE;    //    If new dimensions, then start over.
  151.         }
  152.         if (theChanged & kSetMatrix) {
  153.             myRedraw = TRUE;    //    If new matrix, then start over.
  154.         }
  155.         if (theChanged & kSampleDescChanged) {
  156.             QDrawDescriptionHandle        myQDDesc;
  157.             
  158.             if (myQDDesc = (QDrawDescriptionHandle) MyNewHandleClear(sizeof(QDrawDescription))) {
  159.                 GetMediaSampleDescription(theMedia, theSampleIndex, (SampleDescriptionHandle) myQDDesc);
  160.                 if ((**myQDDesc).version > QDMediaVersion)
  161.                     theEnabled = (**storage).enabled = FALSE; 
  162.                 MyDisposeHandle((Handle *) &myQDDesc);
  163.             } else {
  164.                 theEnabled = (**storage).enabled = FALSE; 
  165.             }
  166.         }
  167.         
  168.         //    Now that everything is updated...
  169.         theChanged = (**storage).somethingChanged = kNoneChanged;
  170.     }
  171.     
  172.     //    If we are playing move backwards, then we must always redraw from last sync frame.
  173.     if (theRate < 0)
  174.         myRedraw = TRUE;
  175.     
  176.     //    We can now assume that everything is setup correctly.  First, the current
  177.     //    frame info is in currPic, currSampleTime, and currSampleIndex.  And, anything that
  178.     //    has changed to the media has been updated.
  179.     //    So, now , we have simplified the problem and we have several steps
  180.     //    to follow depending on myRedraw.
  181.     //        if myRedraw = TRUE: redraw everything since last keyframe
  182.     //        if myRedraw = FALSE: redraw everything since last key frame or last media frame,
  183.     //        whichever is closer to current frame first.
  184.     //    (Drawing is not necessary if myRedraw is false and if theLastMediaTime == currSampleTime
  185.     if (myRedraw || (theLastMediaTime != currSampleTime)) {
  186.         //    Let's start by getting last key frame (use nextTimeEdgeOK in case current
  187.         //    frame is sync frame)  Strangely, if the media doesn't have sync sample, the sample
  188.         //    time returned is the same as the same time passed.  i.e. every frame is a keyframe.
  189.         GetMediaNextInterestingTime(theMedia, nextTimeSyncSample + nextTimeEdgeOK,
  190.                 currSampleTime, -1, &mySampleTime, nil);
  191.         
  192.         //    If myRedraw = FALSE, mySampleTime <= theLastMediaTime, and currSampleTime
  193.         //    is ahead of theLastMediaTime, then let's search to set the place to draw as the sample
  194.         //    after theLastMediaTime.
  195.         //    forward to see if we find the theLastMediaTime.  If we find it, then set myTime
  196.         //    equal to that so that we can begin drawing from there.
  197.         if (!myRedraw && (mySampleTime <= theLastMediaTime) && (theLastMediaTime < currSampleTime)) {
  198.             theTime = mySampleTime;
  199.             
  200.             while (theTime >= 0 && theTime < theLastMediaTime) {
  201.                 GetMediaNextInterestingTime(theMedia, nextTimeMediaSample,
  202.                         theTime, 1, &theTime, nil);
  203.             }
  204.             if (theTime == theLastMediaTime && theTime != -1) {
  205.                 GetMediaNextInterestingTime(theMedia, nextTimeMediaSample,
  206.                         theTime, 1, &theTime, nil);
  207.                 if (theTime != -1) {
  208.                     mySampleTime = theTime;    
  209.                 } else {
  210.                     DebugStr("\PERROR !!!!!");
  211.                 }
  212.             }
  213.         }
  214.         
  215.         //    Now, we are at the right place to begin drawing.  mySampleTime is where we
  216.         //    should start drawing.  Don't draw if the media is disabled.
  217.         done = FALSE;
  218.         theTime = mySampleTime;
  219.         while (!done && theEnabled) {
  220.             if (theTime == currSampleTime) {
  221.                 done = TRUE;
  222.             }
  223.             if ((err = GetMediaSample(theMedia, (Handle) myPic, 0, &mySize,
  224.                     theTime, nil, nil, nil, nil, 0, nil, nil))) {
  225.                 DebugStr("\PGetMediaSample failed.  Do not continue.");
  226.             }
  227.             myDrawRect = (**myPic).picFrame;
  228.             TransformRect(&theTrackMatrix, &myDrawRect, nil);
  229.             DrawPicture(myPic, &myDrawRect);
  230.             if (!done) {
  231.                 GetMediaNextInterestingTime(theMedia, nextTimeMediaSample, theTime, 1, &theTime, nil);
  232.                 if (theTime < 0) {
  233.                     done = TRUE;
  234.                     DebugStr("\PERROR!!!!");
  235.                 }
  236.             }
  237.         }
  238.         
  239.         //    Say we drew somthing.
  240.         *flagsOut |= mDidDraw;
  241.     }
  242.     
  243.     //    Update last media time so that we know what the last current sample is.
  244.     (**storage).lastMediaTime = currSampleTime;
  245.         
  246.     //    Finishup by restoring GWorld and disposing handles.
  247.     SetGWorld ((GWorldPtr) savePort, saveGD);
  248.     MyDisposeHandle((Handle *) &myPic);
  249.     MyDisposeHandle((Handle *) &currPic);
  250.     
  251.     return(err);
  252. }
  253.  
  254. //--------------------------------------------------------------------------
  255.  
  256. pascal ComponentResult MyMediaSetActive(PrivateGlobals **storage,
  257.                                         Boolean enableMedia)
  258. {
  259.     if (DEBUGME)
  260.         DebugStr("\PIn MyMediaSetActive()");
  261.  
  262.     if ((**storage).enabled != enableMedia) {
  263.         (**storage).enabled = enableMedia;
  264.         (**storage).somethingChanged |= kSetActive;
  265.     }
  266.     
  267.     return(noErr);
  268. }
  269.  
  270. //--------------------------------------------------------------------------
  271.  
  272. pascal ComponentResult MyMediaSetRate(PrivateGlobals **storage,
  273.                                         Fixed rate)
  274. {
  275.     if (DEBUGME)
  276.         DebugStr("\PIn MyMediaSetRate()");
  277.  
  278.     //    Save new rate in newMediaRate so that we can compare with previous rate.  If the
  279.     //    new rate is in the same direction, we won't want to redraw again from keyframe.
  280.     if ((**storage).newMediaRate != rate) {
  281.         (**storage).newMediaRate = rate;
  282.         (**storage).somethingChanged |= kSetRate;
  283.     }
  284.     
  285.     return(noErr);
  286. }
  287.  
  288. //--------------------------------------------------------------------------
  289.  
  290. pascal ComponentResult MyMediaTrackEdited(PrivateGlobals **storage)
  291. {
  292.     if (DEBUGME)
  293.         DebugStr("\PIn MyMediaTrackEdited()");
  294.  
  295.     (**storage).somethingChanged |= kTrackEdited;
  296.     
  297.     return(noErr);
  298. }
  299.  
  300. //--------------------------------------------------------------------------
  301.  
  302. pascal ComponentResult MyMediaSetGWorld(PrivateGlobals **storage,
  303.                                         CGrafPtr aPort, GDHandle aGD)
  304. {
  305.     if (DEBUGME)
  306.         DebugStr("\PIn MyMediaSetGWorld()");
  307.  
  308.     //    It is possible for the GWorld to not change, but for this call to occur.
  309.     //    Therefore, to prevent any unnecessary updates, we don't change anything if
  310.     //    both port and gdevice are the same.
  311.     if (((**storage).port != aPort) || ((**storage).device != aGD)) {
  312.         (**storage).port = aPort;    //    Just to make sure something changed
  313.         (**storage).device = aGD;
  314.         (**storage).somethingChanged |= kSetGWorld;
  315.     }
  316.     
  317.     return(noErr);
  318. }
  319.  
  320. //--------------------------------------------------------------------------
  321.  
  322. pascal ComponentResult MyMediaSetDimensions(PrivateGlobals **storage,
  323.                                         Fixed width, Fixed height)
  324. {
  325.     if (DEBUGME)
  326.         DebugStr("\PIn MyMediaSetDimensions()");
  327.  
  328.     SetRect(&((**storage).graphicsBox), 0, 0,
  329.                     (short) (width >> 16), (short) (height >> 16));
  330.     (**storage).somethingChanged |= kSetDimensions;
  331.  
  332.     return(noErr);
  333. }
  334.  
  335. //--------------------------------------------------------------------------
  336.  
  337. pascal ComponentResult MyMediaSetMatrix(PrivateGlobals **storage,
  338.                                         MatrixRecord *trackMovieMatrix)
  339. {
  340.     if (DEBUGME)
  341.         DebugStr("\PIn MyMediaSetMatrix()");
  342.  
  343.     //    Let's not cause unnecessary updates if the matrix doesn't really change.
  344.     //    This can happen in MoviePlayer if the resize button is clicked on, but not
  345.     //    moved.
  346.     if (!EqualMatrix(&((**storage).trackMatrix), trackMovieMatrix)) {
  347.         (**storage).trackMatrix = *trackMovieMatrix;
  348.         (**storage).somethingChanged |= kSetMatrix;
  349.     }
  350.  
  351.     return(noErr);
  352. }
  353.  
  354. //--------------------------------------------------------------------------
  355.  
  356. /*
  357. pascal ComponentResult MyMediaGetTrackOpaque(PrivateGlobals **storage,
  358.                                         Boolean *trackIsOpaque)
  359. {
  360.     if (DEBUGME)
  361.         DebugStr("\PIn MyMediaGetTrackOpaque()");
  362.  
  363.     //    This is toughy.  I'm still unsure whether or not this should be true or false.
  364.     *trackIsOpaque = TRUE;
  365.     
  366.     return(noErr);
  367. }
  368. */
  369.  
  370. //--------------------------------------------------------------------------
  371.  
  372. pascal ComponentResult MyMediaSampleDescriptionChanged(PrivateGlobals **storage,
  373.                                         long index)
  374. {
  375.     if (DEBUGME)
  376.         DebugStr("\PIn MyMediaSampleDescriptionChanged()");
  377.  
  378.     //    The sample description tables stores info such as data version.  This routine is called
  379.     //    if the contents of the sample description table changes.  It doesn't necessarily
  380.     //    get called if the index changes.
  381.     (**storage).sampleDescIndex = index;
  382.     (**storage).somethingChanged |= kSampleDescChanged;
  383.  
  384.     return(noErr);
  385. }
  386.